module atoms
   use precision
   implicit none
   private

   type atom
      private
	  real(adequate) mass
	  integer charge
   end type atom

   public atom, mass, charge, set_mass, set_charge, new, as_string

   interface new
      module procedure atom_new
   end interface new

   interface mass
      module procedure atom_mass
   end interface mass

   interface charge
      module procedure atom_charge
   end interface charge

   interface set_mass
      module procedure set_atom_mass
   end interface set_mass

   interface set_charge
      module procedure set_atom_charge
   end interface set_charge

   interface as_string
      module procedure atom_as_string
   end interface as_string

   contains

   subroutine atom_new (a, name)
      character*(*), intent(in):: name
	  type(atom), intent(out):: a
	  select case(name)
	  case("H")
	     a = atom(1.0, 0)
	  case("He")
	     a = atom(4.0, 0)
	  case("C")
	     a = atom(12.0, 0)
	  case default
	     ! hm...
		 stop "Illegal atom creation attempted."
	  end select 
   end subroutine atom_new

   function atom_mass (a) 
      real(adequate) atom_mass
	  type(atom), intent(in):: a
	  atom_mass = a%mass
   end function atom_mass

   function atom_charge (a) 
      real(adequate) atom_charge
	  type(atom), intent(in):: a
	  atom_charge = a%charge
   end function atom_charge

   function atom_as_string (a)
      type(atom), intent(in):: a
	  character*32 atom_as_string
	  write (atom_as_string, 100) a%mass, a%charge
100 format("atom( ", e14.4, ", ", i2, ")")
   end function atom_as_string

   subroutine set_atom_mass (a, m)
      type(atom), intent(inout):: a
	  real(adequate), intent(in):: m
	  a%mass = m
   end subroutine set_atom_mass

   subroutine set_atom_charge (a, c)
      type(atom), intent(inout):: a
	  integer, intent(in):: c
	  a%charge = c
   end subroutine set_atom_charge

end module atoms


